package aden.SifWar;


// TODO a rendre generique

// TODO faire un autre surface holder

import aden.Generic.GenMain;
import aden.HexEnv.HexEnvView;
import aden.HexEnv.HexEnvWorld.HexEnvIterTile;
import aden.SifWar.SifWarPlayer.PlayerTile;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;


class SifWarView extends HexEnvView
{
    /** The thread that actually draws the animation */
    private Paint mSelectionPaint;
    private Paint mAttackPaint;
    private Paint mMovePaint;
    private Paint mWaitPaint;
    private Paint mAltitudePaint;
    private Paint mFogPaint;
    
    public SifWarView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SifWarUnit mSelection;
    
    public boolean Init(GenMain inMain)
    {
        super.Init(inMain);        

        mCenterPosX = 7;
        mCenterPosY = 6;
        mGrid = 50;

        mSelectionPaint = new Paint();
        mSelectionPaint.setAntiAlias(true);
        mSelectionPaint.setARGB(255, 255, 0, 0);
        mSelectionPaint.setStrokeWidth(5);
                
        mAttackPaint = new Paint();
        mAttackPaint.setAntiAlias(true);
        mAttackPaint.setARGB(255, 255, 0, 0);
        mAttackPaint.setStrokeWidth(5);
                
        mMovePaint = new Paint();
        mMovePaint.setAntiAlias(true);
        mMovePaint.setARGB(255, 0, 0, 255);
        mMovePaint.setStrokeWidth(5);

        mWaitPaint = new Paint();
        mWaitPaint.setAntiAlias(true);
        mWaitPaint.setARGB(255, 0, 255, 0);
        mWaitPaint.setStrokeWidth(5);

        mAltitudePaint = new Paint();
        mAltitudePaint.setAntiAlias(true);
        mAltitudePaint.setARGB(255, 150, 150, 150);
        mAltitudePaint.setStrokeWidth(1);
                
        mFogPaint = new Paint();
        mFogPaint.setAntiAlias(true);
        mFogPaint.setARGB(100, 100, 100, 100);
        mFogPaint.setStrokeWidth(1);
                
        mSelection = null;

        mViewOrderOption = ViewOrderOption_ONLYSELECTION;
        mViewDateOption  = ViewDateOption_BEGINTURN;
        
        return true;
    }

    public SifWarUnit GetSelection() {return mSelection;}
     
    public SifWarWorld GetSifWarWorld() {return (SifWarWorld)mWorld;}
    public SifWarMain GetSifWarMain() {return (SifWarMain)mMain;}
   
    public void Select(float inPosX,float inPosY)
    {
        mSelection = GetSifWarMain().GetPlayerMgr().GetCurrentPlayer().GetTile(GetWorldX(inPosX,inPosY),
        		                               GetWorldY(inPosX,inPosY)).GetUnit();
        RefreshAdd();
	FlushRefresh();
    }

    public boolean RefreshAdd()
    {
    	super.RefreshAdd();

		Canvas canvas = new Canvas(mAddBitmap);

        Canvas theAddCanvas = new Canvas(mAddBitmap);
        int theHeight = GetSifWarWorld().GetHeight();
        int theWidth = GetSifWarWorld().GetWidth();
        for (int theX = 0;
        		theX < theWidth;
        		++theX)
        {
        	for (int theY = 0;
        			theY < theHeight;
        			++theY)
        	{
        		SifWarPlayer.PlayerTile thePlayerTile = GetSifWarMain().GetPlayerMgr().GetCurrentPlayer().GetTile(theX,theY);
        		if (thePlayerTile.HasDrawing()) 
        		{
        			DrawPlayerTile(thePlayerTile,theX,theY,theAddCanvas);
        		}
        	}
        }

    	if (mSelection != null)
    	{

    		float theCurrentPosX = GetTileCenterX(mSelection.GetX(),mSelection.GetY());  
    		float theCurrentPosY = GetTileCenterY(mSelection.GetX(),mSelection.GetY());  
    		float theHexRadius = mGrid / (2 * COS30);

    		for (int i = 0;
    				i < 6;
    				++i)
    		{
    			float theX1 = theCurrentPosX + sHexPtX[i]*theHexRadius;
    			float theY1 = theCurrentPosY + sHexPtY[i]*theHexRadius;
    			float theX2 = theCurrentPosX + sHexPtX[(i+1) % 6]*theHexRadius;
    			float theY2 = theCurrentPosY + sHexPtY[(i+1) % 6]*theHexRadius;

    			canvas.drawLine(theX1,theY1,theX2,theY2,mSelectionPaint);
    		}
    	}
    	return true;
    }

    public boolean RefreshEnv()
    {
        super.RefreshEnv();

        int thePosXMin = AdaptToRangeX(mCenterPosX - (int)(mCanvasWidth / (mGrid *2)) - 1);
        int thePosYMin = AdaptToRangeY(mCenterPosY - (int)(mCanvasHeight / (mGrid *2)) - 1);
        int thePosXMax = AdaptToRangeX(mCenterPosX + (int)(mCanvasWidth / (mGrid *2)) + 1);
        int thePosYMax = AdaptToRangeY(mCenterPosY + (int)(mCanvasHeight / (mGrid *2)) + 1);
        float theHexRadius = mGrid / (2 * COS30);

        Canvas theEnvCanvas = new Canvas(mEnvBitmap);

        float theCurrentPosX, theCurrentPosY;
        
        for (mIterTile.Begin(GetHexEnvWorld(),
                thePosXMin,
                thePosYMin,
                thePosXMax,
                thePosYMax);
                mIterTile.IsNotDone();
                mIterTile.Next())
        {               
            SifWarTile theContent = (SifWarTile)mIterTile.Content();
            // tiles specific rendering
            DrawTile(theContent,mIterTile.GetX(),mIterTile.GetY(),theEnvCanvas);
        }
        return true;
    }

    private boolean DrawTile(SifWarTile inTile,
    		                 int inX,
    		                 int inY,
    		                 Canvas inCanvas)
    {
        float theCurrentPosX = GetTileCenterX(inX,inY);  
        float theCurrentPosY = GetTileCenterY(inX,inY);  
        float theHexRadius = mGrid / (2 * COS30);

        SifWarWorld theWorld = GetSifWarWorld();
        
        inCanvas.drawBitmap(theWorld.GetEnvBitmap(inTile.GetEnv()),
        		                theCurrentPosX-theHexRadius+2,
        		                theCurrentPosY-theHexRadius-2,
        		                mSelectionPaint);
        
        // prise en compte de l'altitude
        Path theStepPath = new Path();
        HexEnvIterTile theIterNeighbours = theWorld.new HexEnvIterTile();
        int theIndex;
        int thePrevIndex;
        for (theIterNeighbours.BeginNeighbours(GetSifWarWorld(),
        		                     inX,inY,1);
        		theIterNeighbours.IsNotDone();
        		theIterNeighbours.Next())
        {
        	int theDeltaAltitude = inTile.GetAltitude() - ((SifWarTile)theIterNeighbours.Content()).GetAltitude(); 
        	if (0 < theDeltaAltitude)
        	{
        		// on affiche un "escalier"
        		float theRatio = (1 - ((float)theDeltaAltitude) / 20);
        		
        		theIndex = theIterNeighbours.GetNeighbourIndex();
        		thePrevIndex = theIndex - 1;
        		
        		if (thePrevIndex == -1)
        		{
        			thePrevIndex = 5;
        		}
        		theStepPath.reset();
        		theStepPath.moveTo(theCurrentPosX + sHexPtX[theIndex]*theHexRadius,
        				           theCurrentPosY + sHexPtY[theIndex]*theHexRadius);
        		theStepPath.lineTo(theCurrentPosX + sHexPtX[thePrevIndex]*theHexRadius,
				                   theCurrentPosY + sHexPtY[thePrevIndex]*theHexRadius);
        		theStepPath.lineTo(theCurrentPosX + sHexPtX[thePrevIndex]*theHexRadius * theRatio,
		                           theCurrentPosY + sHexPtY[thePrevIndex]*theHexRadius * theRatio);
        		theStepPath.lineTo(theCurrentPosX + sHexPtX[theIndex]*theHexRadius * theRatio,
                                   theCurrentPosY + sHexPtY[theIndex]*theHexRadius * theRatio);
        		theStepPath.close();
        		
        		SetSlopeColor(theIndex);
        		
        		inCanvas.drawPath(theStepPath,mAltitudePaint);
        	}
        }
        
        return true;
    }

    private int[] mSlopeColors;
    
    public void SetSlopeColor(int inIndex)
    {
    	if (mSlopeColors == null)
    	{
    		mSlopeColors = new int[6];
    		mSlopeColors[0] = 200;
    		mSlopeColors[1] = 150;
    		mSlopeColors[2] = 100;
    		mSlopeColors[3] = 50;
    		mSlopeColors[4] = 100;
    		mSlopeColors[5] = 150;
    	}
    	
    	// TODO gestion des heures a venir...
    	mAltitudePaint.setARGB(255,mSlopeColors[inIndex],mSlopeColors[inIndex],mSlopeColors[inIndex]);
    }
    
    public static final int ViewOrderOption_ONLYSELECTION = 0;
    public static final int ViewOrderOption_ALLUNITS = 1;
    public static final int ViewOrderOption_Undefined = 2;
    
    private int mViewOrderOption;
    
    public void ChangeViewOrderOption(int inViewOrderOption)
    {
    	mViewOrderOption = inViewOrderOption;
    	RefreshAdd();
    	FlushRefresh();
    }
    

    // TODO voir pour regarder le tour precedent
    public static final int ViewDateOption_BEGINTURN = 0;
    public static final int ViewDateOption_ENDTURN = 1;
    public static final int ViewDateOption_Undefined = 2;
    
    private int mViewDateOption;
    
    public void ChangeViewDateOption(int inViewDateOption)
    {
    	mViewDateOption = inViewDateOption;
    	RefreshAdd();
    	FlushRefresh();
    }
    
    public boolean DrawPlayerTile(SifWarPlayer.PlayerTile inTile,int inX,int inY,Canvas inCanvas)
    {

    	float theCurrentPosX = GetTileCenterX(inX,inY);  
    	float theCurrentPosY = GetTileCenterY(inX,inY);  
    	float theHexRadius = mGrid / (2 * COS30);


    	// dessin de l'unite
    	SifWarUnit theUnit = inTile.GetUnit();
    	if (theUnit != null && 
    			(!theUnit.IsSilenced() ||
    					inTile.GetVisibility() != PlayerTile.Visibility_NO))
    	{
    		// TODO: pas de prise en compte de ViewDateOption pour le moment    		

    		inCanvas.drawBitmap(theUnit.GetBitmap(PlayerTile.Visibility_FULL),
    				theCurrentPosX-theHexRadius,
    				theCurrentPosY-theHexRadius,
    				mSelectionPaint);
    		
    		float theOldMoveStrokeWidth = mMovePaint.getStrokeWidth();
    		float theOldAttackStrokeWidth = mAttackPaint.getStrokeWidth();
    		if (theUnit == mSelection)
    		{
    			mMovePaint.setStrokeWidth(8);
    			mAttackPaint.setStrokeWidth(8);
    		}

    		if (theUnit == mSelection ||
    			mViewOrderOption == ViewOrderOption_ALLUNITS)
    		{
    		float thePreviousX = GetTileCenterX(inX,inY);
    		float thePreviousY = GetTileCenterY(inX,inY);
    		float theCurrentX = GetTileCenterX(inX,inY);
    		float theCurrentY = GetTileCenterY(inX,inY);
    		for (SifWarWayPt theCurrent = theUnit.GetFirstWayPt();
    			 theCurrent != null;
    			 theCurrent = theCurrent.mNext)
    		{
    			if (theCurrent.GetType() == SifWarWayPt.Type_MOOD)
    			{
    				// afficher les bitmaps signalant les changements d'humeur
    				inCanvas.drawBitmap(SifWarUnit.GetMoodBitmap(((SifWarWayPtMood)theCurrent).GetMood()),
    						theCurrentX - 15 + 15,
    						theCurrentY - 15 + 15,
    						mSelectionPaint);
    			}
    			else if (theCurrent.GetType() == SifWarWayPt.Type_RADIO)
    			{
    				// afficher les bitmaps signalant les changements d'humeur
    				inCanvas.drawBitmap(SifWarUnit.GetRadioBitmap(((SifWarWayPtRadio)theCurrent).GetRadio()),
    						theCurrentX - 15 - 40 + 15,
    						theCurrentY - 15 + 15,
    						mSelectionPaint);
    			}
    			else if (theCurrent.GetType() == SifWarWayPt.Type_WAIT)
    			{

    				SifWarWayPtWait theCurrentWait = (SifWarWayPtWait)theCurrent;

    				// TODO a faire
    				inCanvas.drawBitmap(SifWarUnit.GetUnitWaitBitmap(((SifWarWayPtWait)theCurrent).GetWaitType()),
    						theCurrentX - 15 + 15,
    						theCurrentY - 15 - 40 + 15,
    						mSelectionPaint);
    				if (theCurrentWait.GetWaitType() == SifWarUnit.UnitWait_FORUNITTOMOVE ||
    					theCurrentWait.GetWaitType() == SifWarUnit.UnitWait_FORUNITTOATTACK)
    				{
        				float theTargetX = GetTileCenterX(theCurrentWait.GetX(),theCurrentWait.GetY());  
        				float theTargetY = GetTileCenterY(theCurrentWait.GetX(),theCurrentWait.GetY());  
    					inCanvas.drawLine(theCurrentX,theCurrentY - 40,
						          theTargetX,theTargetY,mWaitPaint);
    				}
    			}
    			else if (theCurrent.GetType() == SifWarWayPt.Type_MOVE)
    			{
    				SifWarWayPtMove theCurrentMove = (SifWarWayPtMove)theCurrent;
    				theCurrentX = GetTileCenterX(theCurrentMove.GetX(),theCurrentMove.GetY());  
    				theCurrentY = GetTileCenterY(theCurrentMove.GetX(),theCurrentMove.GetY());  

    				inCanvas.drawLine(thePreviousX,thePreviousY,
    						theCurrentX,theCurrentY,mMovePaint);
    				thePreviousX = theCurrentX;
    				thePreviousY = theCurrentY;
    			}
    			else if (theCurrent.GetType() == SifWarWayPt.Type_ATTACK)
    			{
    				SifWarWayPtAttack theCurrentAttack = (SifWarWayPtAttack)theCurrent;
    				float theTargetX = GetTileCenterX(theCurrentAttack.GetX(),theCurrentAttack.GetY());  
    				float theTargetY = GetTileCenterY(theCurrentAttack.GetX(),theCurrentAttack.GetY());  

    				if (inX == theCurrentAttack.GetX() &&
    					inY == theCurrentAttack.GetY())
    				{
    					// on affiche une croix signalant la fin de l'attaque
    					inCanvas.drawLine(theCurrentX - 10 - 10,theCurrentY - 10,
    							          theCurrentX + 10 - 10,theCurrentY + 10,mAttackPaint);
    					inCanvas.drawLine(theCurrentX + 10 - 10,theCurrentY - 10,
						          theCurrentX - 10 - 10,theCurrentY + 10,mAttackPaint);
    				}
    				else
    				{
    					inCanvas.drawLine(theCurrentX,theCurrentY,
    							          theTargetX,theTargetY,mAttackPaint);
    				}
    				thePreviousX = theCurrentX;
    				thePreviousY = theCurrentY;
    			}
    		}    
    		}
    		if (theUnit == mSelection)
    		{
    			mMovePaint.setStrokeWidth(theOldMoveStrokeWidth);
    			mAttackPaint.setStrokeWidth(theOldAttackStrokeWidth);
    		}
    	}

    	if (inTile.GetVisibility() == PlayerTile.Visibility_FULL)
    	{
    		// on represente les traces de passages
    	}
    	else if (inTile.GetVisibility() == PlayerTile.Visibility_CLOSE)
    	{
    		// rien
    	}
    	else
    	{
    		Path theShadePath;
    		
    		switch (inTile.GetVisibility())
    		{
    		case PlayerTile.Visibility_FULL:
    			// TODO trace de passage
    			break;
    		case PlayerTile.Visibility_CLOSE:
    			break;
    		case PlayerTile.Visibility_BLURRED:
        		theShadePath = CalculateCellPath(theCurrentPosX,theCurrentPosY,theHexRadius);
    			mFogPaint.setARGB(100, 150, 150, 150);
        		inCanvas.drawPath(theShadePath,mFogPaint);
    			break;
    		case PlayerTile.Visibility_FAR:
        		theShadePath = CalculateCellPath(theCurrentPosX,theCurrentPosY,theHexRadius);
    			mFogPaint.setARGB(100, 100, 100, 100);
        		inCanvas.drawPath(theShadePath,mFogPaint);
    			break;
    		case PlayerTile.Visibility_NO:
        		theShadePath = CalculateCellPath(theCurrentPosX,theCurrentPosY,theHexRadius);
    			mFogPaint.setARGB(100, 50, 50, 50);
        		inCanvas.drawPath(theShadePath,mFogPaint);
    			break;
    		}
    	}
    	

    	// historique sur la tile ...
    	if (inTile.GetVisibility() != PlayerTile.Visibility_NO)
    	{
    		SifWarUnit theEnnemyUnit = inTile.GetEnnemyUnit();
    		if (theEnnemyUnit != null)
    		{
    			// unite ennemie ??
	    		inCanvas.drawBitmap(theEnnemyUnit.GetBitmap(inTile.GetVisibility()),
	    				theCurrentPosX-theHexRadius,
	    				theCurrentPosY-theHexRadius,
	    				mSelectionPaint);
    		}
    	}

    	return true;
    }

    public boolean RefreshTile(SifWarTile inTile,
    		int inX,
            int inY)
    {
        Canvas theEnvCanvas = new Canvas(mEnvBitmap);
    	DrawTile(inTile,inX,inY,theEnvCanvas);
    	
    	SifWarPlayer.PlayerTile thePlayerTile = GetSifWarMain().GetPlayerMgr().GetCurrentPlayer().GetTile(inX,inY);
    	if (thePlayerTile.HasDrawing()) 
    	{
            Canvas theAddCanvas = new Canvas(mAddBitmap);
    		DrawPlayerTile(thePlayerTile,inX,inY,theAddCanvas);
    	}
    	FlushRefresh();
    	return true;
    }
}

// faire les tools de bases: le zoom (contraint au pan ??), le select

// tester l'affichage des unites en bitmap, + l'environnement en transparence

// les actions seront faites dans le menu

// les autres tools sont dans les actions associees

// les unites



